<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IndexedDB数据库</title>
    <style>
        button {
            color: white;
            padding: 0 18px;
            height: 38px;
            border: 1px solid transparent;
            background-color: #16baaa;
            border-radius: 2px;
            box-sizing: border-box;
            cursor: pointer;
        }

        button:hover {
            opacity: .8;
        }

        #menu {
            justify-items: stretch;
            justify-content: center;
            display: grid;
            gap: 16px;
            grid-template-columns: max-content;
            grid-auto-rows: auto;
        }
    </style>
</head>

<body>
    <div id="menu">
        <button type="button" onclick="createDB()">生成数据库并添加数据</button>
        <button type="button" onclick="deleteDB()">删除数据库</button>
        <button type="button" onclick="readDBByKey()">根据主键查询数据</button>
        <button type="button" onclick="readDBByIndex()">根据索引查询数据</button>
    </div>
    <script>
        function getDatabaseNames() {
            return indexedDB.databases().then(dbs => dbs.map(db => db.name));
        }

        async function deleteDB() {
            let dbNames = await getDatabaseNames();
            if (!dbNames.includes('USER')) {
                console.log('数据库USER不存在');
                return;
            }
            let openRequest = window.indexedDB.deleteDatabase('USER');
            openRequest.onsuccess = event => {
                console.log('数据库USER删除成功', event);
            }
            openRequest.onerror = event => {
                console.log('数据库USER删除失败', event);
            }
        }

        async function createDB() {
            let dbNames = await getDatabaseNames();
            if (dbNames.includes('USER')) {
                console.log('数据库USER已存在');
                return;
            }
            // 打开数据库,如果指定的数据库不存在，就会新建数据库。第二个参数是整数，表示数据库的版本。
            // 如果省略版本，打开已有数据库时，默认为当前版本；新建数据库时，默认为 1 
            let openRequest = window.indexedDB.open('USER');
            // 第一次创建数据库时也会触发（版本从0到1）
            openRequest.onupgradeneeded = event => {
                console.log('数据库版本升级事件', event);
                let db = event.target.result;
                if (!db.objectStoreNames.contains('user1')) {
                    // 不指定主键，自行插入
                    var uesr1 = db.createObjectStore('user1');
                }
                if (!db.objectStoreNames.contains('user2')) {
                    // 指定插入的数据的id属性值作为主键
                    var user2 = db.createObjectStore('user2', { keyPath: 'id' });
                    //建立索引，索引的意义在于，可以让你搜索任意字段，也就是说从任意字段拿到数据记录。
                    //如果不建立索引，默认只能搜索主键（即从主键取值）
                    user2.createIndex('name', 'name', { unique: false });
                }
                if (!db.objectStoreNames.contains('user3')) {
                    // 主键自动递增
                    var user3 = db.createObjectStore('user3', { autoIncrement: true });
                    uesr1.transaction.oncomplete = event => {
                        //如果要在新建表后做插入数据等操作，需要放在这里
                        //addUser();
                    }
                }
            }
            // onupgradeneeded比onsuccess先调用
            openRequest.onsuccess = event => {
                console.log('数据库打开成功', event);
                addUser(event.target.result);
            }

            openRequest.onerror = event => {
                console.log('数据库打开失败', event);
            }
        }

        // 添加数据
        function addUser(db) {
            let trans = db.transaction(['user1', 'user2', 'user3'], 'readwrite');

            let user1AddRequest = trans.objectStore('user1').add({ id: 123, name: 'lisi', age: 23 }, '12423232');
            user1AddRequest.onsuccess = event => {
                console.log('User1插入数据成功', event);
            }
            user1AddRequest.onerror = event => {
                console.error('User1插入数据失败', event);
            };

            let user2AddRequest = trans.objectStore('user2').add({ id: 123, name: 'lisi', age: 23 });
            trans.objectStore('user2').add({ id: 456, name: 'zaoliu', age: 28 });

            user2AddRequest.onsuccess = event => {
                console.log('User2插入数据成功', event);
            }

            let user3AddRequest = trans.objectStore('user3').add({ id: 123, name: 'lisi', age: 23 });
            user3AddRequest.onsuccess = event => {
                console.log('User3插入数据成功', event);
            }

            trans.oncomplete = event => {
                console.log('数据插入事务完成', event);
            }
            trans.onerror = event => {
                console.error('数据插入事务失败', event);
            };
        }

        // 将打开数据库封装成promise
        function openDatabase(name) {
            return new Promise((resolve, reject) => {
                let openRequest = window.indexedDB.open(name);
                openRequest.onsuccess = event => {
                    resolve(event.target.result)
                }

                openRequest.onerror = event => {
                    reject(`open IDBDatabase: ${name} failed`)
                }
            });
        }

        //根据主键查询数据
        function readDBByKey() {
            openDatabase('USER').then(db => {
                let trans = db.transaction(['user2']);
                let user2 = trans.objectStore('user2')
                // 根据主键查询, bound默认是左右都是闭区间
                let request1 = user2.getAll(IDBKeyRange.bound(123, 456));
                request1.onsuccess = event => {
                    let dataArr = event.target.result;
                    if (dataArr) {
                        console.log(dataArr);
                    }
                    else {
                        console.log('未查询到数据');
                    }
                }
                // 遍历整个表（user2.getAll()不传参数也能一次性取出所有数据）
                let request2 = user2.openCursor();
                request2.onsuccess = event => {
                    let cursor = event.target.result;
                    if (cursor) {
                        console.log(cursor.key, cursor.value);
                        cursor.continue()
                    }
                }
                // 修改用IDBObjectStore.put(item, key?)
                // 删除用IDBObjectStore.delete(key)
            }).catch(console.log);
        }

        // 根据索引查询数据
        function readDBByIndex() {
            openDatabase('USER').then(db => {
                let trans = db.transaction(['user2']);
                let user2 = trans.objectStore('user2')
                let index = user2.index('name')
                let request = index.get('zaoliu');
                request.onsuccess = event => {
                    console.log(event.target.result);
                }
            }).catch(console.log);
        }
    </script>
</body>

</html>